/*
 * Copyright (c) 2010-2021 Belledonne Communications SARL.
 *
 * This file is part of linphone-android
 * (see https://www.linphone.org).
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.newlink.building.compatibility

import android.Manifest
import android.annotation.TargetApi
import android.app.*
import android.content.Context
import android.content.Intent
import androidx.core.content.ContextCompat
import com.newlink.building.NL_App.Companion.coreContext
import com.newlink.building.NL_App.Companion.corePreferences
import com.newlink.building.R
import com.newlink.building.notifications.Notifiable
import com.newlink.building.notifications.NotificationsManager
import com.newlink.building.utils.Module_Phone_ImageUtils
import com.newlink.building.utils.Module_Phone_LinphoneUtils
import org.linphone.core.Call
import org.linphone.core.tools.Log

@TargetApi(31)
class Module_Phone_Api31Compatibility {
    companion object {
        fun getUpdateCurrentPendingIntentFlag(): Int {
            return PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
        }

        fun createIncomingCallNotification(
            context: Context,
            call: Call,
            notifiable: Notifiable,
            pendingIntent: PendingIntent,
            notificationsManager: NotificationsManager
        ): Notification {
            val contact = coreContext.contactsManager.findContactByAddress(call.remoteAddress)
            val roundPicture = Module_Phone_ImageUtils.getRoundBitmapFromUri(context, contact?.getThumbnailUri())
            val displayName = contact?.name ?: Module_Phone_LinphoneUtils.getDisplayName(call.remoteAddress)

            val person = notificationsManager.getPerson(contact, displayName, roundPicture)
            val caller = Person.Builder()
                .setName(person.name)
                .setIcon(person.icon?.toIcon(context))
                .setUri(person.uri)
                .setKey(person.key)
                .setImportant(person.isImportant)
                .build()

            val declineIntent = notificationsManager.getCallDeclinePendingIntent(notifiable)
            val answerIntent = notificationsManager.getCallAnswerPendingIntent(notifiable)

            val isVideoEnabledInRemoteParams = call.remoteParams?.isVideoEnabled ?: false
            val isVideoAutomaticallyAccepted = call.core.videoActivationPolicy.automaticallyAccept
            val isVideo = isVideoEnabledInRemoteParams && isVideoAutomaticallyAccepted

            val builder = Notification.Builder(
                context,
                context.getString(R.string.notification_channel_incoming_call_id)
            )
                .setStyle(
                    Notification.CallStyle.forIncomingCall(
                        caller,
                        declineIntent,
                        answerIntent
                    ).setIsVideo(isVideo)
                )
                .setSmallIcon(R.drawable.icon_makecall)
                .setCategory(Notification.CATEGORY_CALL)
                .setVisibility(Notification.VISIBILITY_PUBLIC)
                .setWhen(System.currentTimeMillis())
                .setAutoCancel(false)
                .setShowWhen(true)
                .setOngoing(true)
                .setColor(ContextCompat.getColor(context, R.color.green))
                .setFullScreenIntent(pendingIntent, true)

            if (!corePreferences.preventInterfaceFromShowingUp) {
                builder.setContentIntent(pendingIntent)
            }

            return builder.build()
        }

        fun createCallNotification(
            context: Context,
            call: Call,
            notifiable: Notifiable,
            pendingIntent: PendingIntent,
            channel: String,
            notificationsManager: NotificationsManager
        ): Notification {
            val contact =
                coreContext.contactsManager.findContactByAddress(call.remoteAddress)
            val roundPicture = Module_Phone_ImageUtils.getRoundBitmapFromUri(context, contact?.getThumbnailUri())
            val displayName =
                contact?.name ?: Module_Phone_LinphoneUtils.getDisplayName(call.remoteAddress.username)

            val isVideo = call.currentParams.isVideoEnabled
            val iconResourceId: Int = when (call.state) {
                Call.State.Paused, Call.State.Pausing, Call.State.PausedByRemote -> {
                    R.drawable.head_in_call
                }

                else -> {
                    if (isVideo) {
                        R.drawable.head_in_call
                    } else {
                        R.drawable.head_in_call
                    }
                }
            }
            val stringResourceId: Int
            when (call.state) {
                Call.State.Paused, Call.State.Pausing, Call.State.PausedByRemote -> {
                    stringResourceId = R.string.call_notification_paused
                }

                Call.State.OutgoingRinging, Call.State.OutgoingProgress, Call.State.OutgoingInit, Call.State.OutgoingEarlyMedia -> {
                    stringResourceId = R.string.call_notification_outgoing
                }

                else -> {
                    stringResourceId = R.string.call_notification_active
                }
            }

            val person = notificationsManager.getPerson(contact, displayName, roundPicture)
            val caller = Person.Builder()
                .setName(person.name)
                .setIcon(person.icon?.toIcon(context))
                .setUri(person.uri)
                .setKey(person.key)
                .setImportant(person.isImportant)
                .build()
            val declineIntent = notificationsManager.getCallDeclinePendingIntent(notifiable)
            val builder = Notification.Builder(
                context, channel
            )
                .setContentTitle(contact?.name ?: displayName)
                .setContentText(context.getString(stringResourceId))
//                .setStyle(Notification.CallStyle.forOngoingCall(caller, declineIntent).setIsVideo(isVideo))
                .setSmallIcon(iconResourceId)
                .setAutoCancel(false)
                .setCategory(Notification.CATEGORY_CALL)
                .setVisibility(Notification.VISIBILITY_PUBLIC)
                .setWhen(System.currentTimeMillis())
                .setShowWhen(true)
                .setOngoing(true)
                .setColor(ContextCompat.getColor(context, R.color.colorPrimary))
                .setFullScreenIntent(
                    pendingIntent,
                    true
                ) // This is required for CallStyle notification

            if (!corePreferences.preventInterfaceFromShowingUp) {
                builder.setContentIntent(pendingIntent)
            }

            return builder.build()
        }

        fun startForegroundService(context: Context, intent: Intent) {
            try {
                context.startForegroundService(intent)
            } catch (fssnae: ForegroundServiceStartNotAllowedException) {
                Log.e("[Api31 Compatibility] Can't start service as foreground! $fssnae")
            }
        }

        fun startForegroundService(service: Service, notifId: Int, notif: Notification?) {
            try {
                service.startForeground(notifId, notif)
            } catch (fssnae: ForegroundServiceStartNotAllowedException) {
                Log.e("[Api31 Compatibility] Can't start service as foreground! $fssnae")
            }
        }

        fun hasBluetoothConnectPermission(context: Context): Boolean {
            return Module_Phone_Compatibility.hasPermission(context, Manifest.permission.BLUETOOTH_CONNECT)
        }
    }
}
